﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace QDCommon.Secret
{
    public class AESHelper
    {
        public static string EncryptText(string input, string key, string salt)
        {
            if (salt.Length < 8)
            {

                throw new Exception("salt 最少长度 8");
            }
            string result = "";

            var saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] inputEncrypted = Encoding.UTF8.GetBytes(input);
            byte[] keyBytes = Encoding.UTF8.GetBytes(key);
            using (var sha = SHA256.Create())
            {
                keyBytes = sha.ComputeHash(keyBytes);

                byte[] bytesEncrypted = AESEncryptBytes(inputEncrypted, keyBytes, saltBytes);

                result = Convert.ToBase64String(bytesEncrypted);
            }
            return result;
        }

        private static byte[] AESEncryptBytes(byte[] bytesToBeEncrypted, byte[] passwordBytes, byte[] salt)
        {
            byte[] encryptedBytes = null;


            using (var ms = new MemoryStream())
            {
                using (var AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000))
                    {
                        AES.Key = key.GetBytes(32);
                        AES.IV = key.GetBytes(16);

                        AES.Mode = CipherMode.CBC;

                        using (var cs = new CryptoStream(ms, AES.CreateEncryptor(),
                            CryptoStreamMode.Write))
                        {
                            cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                            cs.Close();
                        }

                        encryptedBytes = ms.ToArray();
                    }
                }
            }

            return encryptedBytes;
        }

        public static string DecryptText(string input, string key, string salt)
        {
            string result = "";
            var saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] bytesToBeDecrypted = Convert.FromBase64String(input);

            byte[] keyBytes = Encoding.UTF8.GetBytes(key);
            using (var sha = SHA256.Create())
            {
                keyBytes = sha.ComputeHash(keyBytes);

                byte[] bytesDecrypted = AESDecryptBytes(bytesToBeDecrypted, keyBytes, saltBytes);

                result = Encoding.UTF8.GetString(bytesDecrypted);
            }
            return result;
        }

        public static byte[] AESDecryptBytes(byte[] bytesToBeDecrypted, byte[] keyBytes, byte[] salt)
        {
            byte[] decryptedBytes = null;


            using (var ms = new MemoryStream())
            {
                using (var AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    using (var key = new Rfc2898DeriveBytes(keyBytes, salt, 1000))
                    {
                        AES.Key = key.GetBytes(32);
                        AES.IV = key.GetBytes(16);

                        AES.Mode = CipherMode.CBC;

                        using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                            cs.Close();
                        }

                        decryptedBytes = ms.ToArray();
                    }
                }
            }

            return decryptedBytes;
        }
    }
}

